package com.gagakuai.session;

import com.gagakuai.bind.MapperRegistry;
import com.gagakuai.executor.Executor;
import com.gagakuai.mapping.BoundSql;
import com.gagakuai.mapping.Environment;
import com.gagakuai.mapping.MappedStatement;
import com.gagakuai.reflect.DefaultReflectFactory;
import com.gagakuai.reflect.factory.ObjectFactory;
import com.gagakuai.reflect.factory.ReflectorFactory;
import com.gagakuai.statement.StatementHandler;
import com.gagakuai.transcation.Transaction;
import com.gagakuai.type.JdbcType;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/*
 * @program: settement
 * @description:
 * @author: houhong
 * @create: 2022-11-09 00:29
 */
public class Configuration {


    protected Environment environment;

    protected boolean safeRowBoundsEnabled;
    protected boolean safeResultHandlerEnabled = true;
    protected boolean mapUnderscoreToCamelCase;
    protected boolean aggressiveLazyLoading;
    protected boolean multipleResultSetsEnabled = true;
    protected boolean useGeneratedKeys;
    protected boolean useColumnLabel = true;


    protected JdbcType jdbcTypeForNull = JdbcType.OTHER;

    /*
     * 是否开启缓存
     */
    protected boolean cacheEnabled = true;
    protected boolean callSettersOnNulls;
    protected boolean useActualParamName = true;
    protected boolean returnInstanceForEmptyRow;


    protected Properties variables = new Properties();
    protected ReflectorFactory reflectorFactory = new DefaultReflectFactory();
    protected ObjectFactory objectFactory = new DefaultObjectFactory();

    protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

    /*
     * 注册mapper和 MapperProxyFactory 的映射
     */
    protected MapperRegistry mapperRegistry = new MapperRegistry(this);


    /*
     * 懒加载
     */
    protected boolean lazyLoadingEnabled = false;


    protected String databaseId;

    protected Class<?> configurationFactory;


    /*
     * 用于处理Mapper中的<seelct> <update> 等标签，或者处理@Select ,@Update.@Delete
     * 等标注的信息 key= Mapper 中的id  value 是MapperStatement 对象
     */
    protected final Map<String, MappedStatement> mappedStatements = new StrictMap<>("Mapped Statements collection");


    public Configuration() {
    }

    /*
     * @param transaction:事务
     * @param type：类型
     * @return {@link Executor}
     * @Author houhong
     * @Description 获取一个执行器，工厂
     * @Date 9:04 下午 2023/6/29
     */
    public Executor newExecutor(Transaction transaction, ExecutorType type) {

        type = type == null ? defaultExecutorType : type;
        type = type == null ? ExecutorType.SIMPLE : type;

        Executor executor;
        //todo

        return executor;

    }

    public StatementHandler newStatementHandler(Executor executor, MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {



    }


    public JdbcType getJdbcTypeForNull() {
        return jdbcTypeForNull;
    }


    public ExecutorType getDefaultExecutorType() {
        return defaultExecutorType;
    }

    public void setDefaultExecutorType(ExecutorType defaultExecutorType) {
        this.defaultExecutorType = defaultExecutorType;
    }

    public Configuration(Environment environment) {
        this();
        this.environment = environment;
    }


    public Environment getEnvironment() {
        return environment;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }


    protected static class StrictMap<V> extends HashMap<String, V> {

        private static final long serialVersionUID = -4950446264854982944L;
        private final String name;

        public StrictMap(String name, int initialCapacity, float loadFactor) {
            super(initialCapacity, loadFactor);
            this.name = name;
        }

        public StrictMap(String name, int initialCapacity) {
            super(initialCapacity);
            this.name = name;
        }

        public StrictMap(String name) {
            super();
            this.name = name;
        }

        public StrictMap(String name, Map<String, ? extends V> m) {
            super(m);
            this.name = name;
        }

        @Override
        @SuppressWarnings("unchecked")
        public V put(String key, V value) {
            if (containsKey(key)) {
                throw new IllegalArgumentException(name + " already contains value for " + key);
            }
            if (key.contains(".")) {
                final String shortKey = getShortName(key);
                if (super.get(shortKey) == null) {
                    super.put(shortKey, value);
                } else {
                    super.put(shortKey, (V) new Ambiguity(shortKey));
                }
            }
            return super.put(key, value);
        }

        public V get(Object key) {
            V value = super.get(key);
            if (value == null) {
                throw new IllegalArgumentException(name + " does not contain value for " + key);
            }
            if (value instanceof Ambiguity) {
                throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name
                        + " (try using the full name including the namespace, or rename one of the entries)");
            }
            return value;
        }

        private String getShortName(String key) {
            final String[] keyParts = key.split("\\.");
            return keyParts[keyParts.length - 1];
        }

        protected static class Ambiguity {
            final private String subject;

            public Ambiguity(String subject) {
                this.subject = subject;
            }

            public String getSubject() {
                return subject;
            }
        }
    }
}